/** @file    EncoderProtocolPlainText.cpp
 *  @author  Alessandro Polo
 *  @version $Id: EncoderProtocolPlainText.cpp 2832 2010-08-02 22:53:46Z alex $
 *  @brief
 * File containing methods for the wosh::persistence::plaintext::EncoderProtocolPlainText class.
 * The header for this class can be found in EncoderProtocolPlainText.h, check that file
 * for class description.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/
 
 #include <framework/persistence/plaintext/EncoderProtocolPlainText.h>

 #include <core/ObjectFactory.h>
 #include <core/Utilities.h>
 #include <core/SystemError.h>
 #include <core/FileSystem.h>
 #include <core/DataModels.h>
 #include <core/MethodsCommon.h>

 #include <sstream>


namespace wosh {
 namespace persistence {
  namespace plaintext {

 //WOSH_REGISTER_INTERFACE(wosh::persistence::plaintext::PersistencePlainText, "wosh::PersistenceDb", 1.01, _static_PersistencePlainText )
 WOSH_REGISTER_INTERFACE(wosh::persistence::plaintext::EncoderBasePlainText, "wosh::EncoderBase", 1.00, _static_EncoderBasePlainText )

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 WOSH_REGISTER(wosh::persistence::plaintext::EncoderProtocolPlainText, "wosh::EncoderProtocol", 1.01, _static_EncoderProtocolPlainText )

EncoderProtocolPlainText::EncoderProtocolPlainText()
	: EncoderProtocol() {
	Object::setName("EncoderProtocolPlainText" );
 }
/*
EncoderBase* EncoderProtocolPlainText::getEncoderFor_( const char* classname, double version, bool recursive ) {
	ObjectTypeInfo info(classname, "", version, true);
	if ( getEncoders().exists(info) )
		return getEncoders().find(info);
	if ( !recursive )
		return NULL;
	std::vector<ObjectTypeInfo> class_list;
	WRESULT ret = ObjectFactory::gatherInfoOf(class_list, classname, version);
	if ( WFAILED(ret) || class_list.empty() )
		return NULL;
	std::vector<ObjectTypeInfo>::const_iterator it;
	for (it=class_list.begin(); it!=class_list.end(); ++it) {
		if ( (*it).name == info.name ) continue;
		if ( getEncoders().exists(*it) )
			return getEncoders().find(*it);
		EncoderBase* enc = getEncoderFor_( (*it).name.c_str(), (*it).version, recursive );
		if ( enc != NULL )
			return enc;
	 }
	return NULL;
 }
*/
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderProtocolPlainText::serializeTo( const ISerializable* object, std::ostream& output_stream, int encoder_options ) {
	if ( object == NULL ) return WRET_ERR_PARAM;
	getEncoders().transactionBeginRead();
	EncoderBasePlainText* enc = dynamic_cast<EncoderBasePlainText*>( getEncoderFor_(object->getClassName()) );
	if ( enc == NULL ) {
		output_stream << object->toString(); // at least print something
		getEncoders().transactionEnd();
		return WRET_ERR_ILLEGAL_USE;
	 }
	WRESULT ret = enc->serializeTo(object, output_stream, encoder_options);
	getEncoders().transactionEnd();
	return ret;
 }

WRESULT EncoderProtocolPlainText::deserializeFrom( ISerializable* object, std::istream& input_stream ) {
	if ( object == NULL ) return WRET_ERR_PARAM;
	getEncoders().transactionBeginRead();
	EncoderBasePlainText* enc = dynamic_cast<EncoderBasePlainText*>( getEncoderFor_(object->getClassName()) );
	if ( enc == NULL ) {
		getEncoders().transactionEnd();
		return WRET_ERR_ILLEGAL_USE;
	 }
	WRESULT ret = enc->deserializeFrom(object, input_stream);
	getEncoders().transactionEnd();
	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

int64 EncoderBasePlainText::serializeTo( const ISerializable* object, char* output, int64 buffer_size, int encoder_options ) {
	std::ostringstream oss;
	oss.rdbuf()->pubsetbuf(output, (std::streamsize)buffer_size);
	WRESULT ret = this->serializeTo(object, oss, encoder_options);
	if ( WFAILED(ret) ) return -1;
	return oss.str().size(); // SO LAME
 }

int64 EncoderBasePlainText::deserializeFrom( ISerializable* , const char* , int64 ) {
	return 0;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

unsigned int EncoderBasePlainText::evalStringSize( const wosh::ISerializable* object, unsigned int maxsize ) {
	if ( object == NULL ) return 0;
	if ( object->isKindOf<Variant>() ) {
		const wosh::Variant* obj_data = dynamic_cast<const wosh::Variant*>( object );
		if ( obj_data == NULL ) return 0;
		if ( obj_data->isStringNotEmpty() )
			return _GET_Min(obj_data->asString().size(), maxsize);
		return _GET_Min(obj_data->toString().size(), maxsize);
	 }
	else if ( object->isKindOf<Permission>() ) {
		const wosh::Permission* obj_perm = dynamic_cast<const wosh::Permission*>( object );
		if ( obj_perm == NULL ) return 0;
		return _GET_Min(obj_perm->toUnixStyle_size(), maxsize);
	 }
	else { // DEPRECATED
		std::string temp = object->toString();
		return _GET_Min(temp.size(), maxsize);
	}
	return 0;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

  }; // namespace plaintext
 }; // namespace persistence
}; // namespace wosh
